<template>
    <div class="quartz_manage_span">
        <table-span :current-page="tabelData.current" :page-size="tabelData.size" :total="tabelData.total"
            :isShowTool="false" :size-change="handleSizeChange" :current-change="handleCurrentChange">
            <template v-slot:searchItem>
                <div class="search_item_span search_item_fix_width">
                    <el-input size="default" v-model="searchCondition.jobName" placeholder="请输入任务名称" clearable></el-input>
                </div>
                <div class="search_item_span">
                    <el-button icon="Search" size="default" type="primary" @click="searchData">查询</el-button>
                </div>
                <div class="search_item_span">
                    <el-button icon="Plus" size="default" type="primary" :disabled="!(btOption.btQuartzJobSave)"
                        @click="openDialog(null, null)">新增定时任务</el-button>
                </div>
            </template>
            <template v-slot:searchTable>
                <el-table :data="tabelData.records" size="default" :show-overflow-tooltip=true height="100%"
                    style="width: 100%;">
                    <el-table-column align="center" type="index" width="50">
                    </el-table-column>
                    <el-table-column align="center" prop="jobName" label="任务名称" min-width="120">
                    </el-table-column>
                    <el-table-column align="center" prop="description" label="任务备注" min-width="120">
                    </el-table-column>
                    <el-table-column align="center" prop="triggerTypeName" label="执行频率" min-width="140">
                    </el-table-column>
                    <el-table-column align="center" prop="jobClassName" label="执行类" width="120">
                    </el-table-column>
                    <el-table-column align="center" prop="startTime" label="开始时间" width="240">
                    </el-table-column>
                    <el-table-column align="center" prop="endTime" label="结束时间" width="240">
                    </el-table-column>
                    <el-table-column align="center" prop="nextFireTime" label="下次时间" width="240">
                    </el-table-column>
                    <el-table-column align="center" label="任务状态" width="120">
                        <template #default="scope">
                            <el-switch v-model="scope.row.jobStatus" inline-prompt :active-value="0" :inactive-value="1"
                                active-text="启用" inactive-text="禁用"
                                style="--el-switch-on-color: #409eff; --el-switch-off-color: #f56c6c"
                                :loading="scope.row.loading" :before-change="jobRunOrStop.bind(this, scope.row)"
                                :disabled="!btOption.btQuartzRunOrStop" />
                        </template>
                    </el-table-column>
                    <el-table-column fixed="right" align="center" label="操作" width="420">
                        <template #default="scope">
                            <el-button size="small" type="primary" :disabled="!(btOption.btQuartzExecLog)"
                                @click="openLogDialog(scope.$index, scope.row, 0)">执行日志</el-button>
                            <el-button size="small" type="primary" :disabled="!(btOption.btQuartzOperateLog)"
                                @click="openLogDialog(scope.$index, scope.row, 1)">操作日志</el-button>
                            <el-button size="small" type="success" :disabled="!(btOption.btQuartzExec)"
                                @click="executeOnce(scope.$index, scope.row)">执行一次</el-button>
                            <el-button size="small" :disabled="!(btOption.btQuartzJobUpdate)"
                                @click="openDialog(scope.$index, scope.row)"
                                v-if="scope.row.jobGroup != 'FIXED_GROUP'">编辑</el-button>
                            <el-button size="small" type="danger" :disabled="!(btOption.btQuartzJobDelete)"
                                @click="btDelete(scope.$index, scope.row)"
                                v-if="scope.row.jobGroup != 'FIXED_GROUP'">删除</el-button>
                        </template>
                    </el-table-column>
                </el-table>
            </template>
        </table-span>
        <el-dialog v-model="saveUpdateDialogOption.show" :title="saveUpdateDialogOption.title" width="450px"
            :close-on-click-modal="false" :close-on-press-escape="false" :before-close="saveUpdateBeforeClose"
            @close="saveUpdateDialogClose">
            <el-form ref="saveUpdateFormRef" :model="saveUpdateForm" :rules="saveUpdateFormRules" label-width="100px"
                status-icon>
                <el-form-item label="任务名称" prop="jobName">
                    <el-input v-model="saveUpdateForm.jobName" placeholder="请填写定时任务名称" :clearable="true" show-word-limit
                        maxlength="100"></el-input>
                </el-form-item>
                <el-form-item label="任务说明" prop="description">
                    <el-input v-model="saveUpdateForm.description" placeholder="请填写定时任务说明" :clearable="true" show-word-limit
                        maxlength="500"></el-input>
                </el-form-item>
                <el-form-item label="执行类名" prop="jobClassName">
                    <el-input v-model="saveUpdateForm.jobClassName" placeholder="请填写定时任务类名" :clearable="true"></el-input>
                </el-form-item>
                <el-form-item label="开始时间" prop="startAt">
                    <el-date-picker style="width: 310px;" v-model="saveUpdateForm.startAt"
                        value-format="YYYY-MM-DD HH:mm:ss" type="datetime" placeholder="请选择开始时间" />
                </el-form-item>
                <el-form-item label="开始时间" prop="endAt">
                    <el-date-picker style="width: 310px;" v-model="saveUpdateForm.endAt" value-format="YYYY-MM-DD HH:mm:ss"
                        type="datetime" placeholder="请选择结束时间" />
                </el-form-item>
                <el-form-item label="频率类型" prop="quartzType">
                    <el-select style="width: 310px;" v-model="saveUpdateForm.quartzType" placeholder="请选择执行频率类型">
                        <el-option v-for="item in quartzTypeList" :key="item.value" :label="item.label"
                            :value="item.value" />
                    </el-select>
                </el-form-item>
                <el-form-item label="cron表达式" prop="cron" v-if="saveUpdateForm.quartzType == 1">
                    <el-input v-model="saveUpdateForm.cron" placeholder="请填写cron表达式" :clearable="true"></el-input>
                </el-form-item>
                <el-form-item label="频率间隔" prop="interval" v-if="saveUpdateForm.quartzType == 0">
                    <el-input-number style="width: 280px;" v-model="saveUpdateForm.interval" :min="1" />
                    <el-text style="width: 20px;margin-left:10px;">秒</el-text>
                </el-form-item>
                <el-form-item label="重复次数" prop="repeatCount" v-if="saveUpdateForm.quartzType == 0">
                    <el-input-number style="width: 280px;" v-model="saveUpdateForm.repeatCount" :min="1" />
                    <el-text style="width: 20px;margin-left:10px;">次</el-text>
                </el-form-item>
            </el-form>
            <template #footer>
                <span class="dialog-footer">
                    <el-button @click="saveUpdateBeforeClose">取消</el-button>
                    <el-button type="primary" @click="confirmSaveUpdateDialog">
                        保存
                    </el-button>
                </span>
            </template>
        </el-dialog>
        <el-dialog v-model="logDialogOption.show" :title="logDialogOption.title" width="640px" :close-on-click-modal="false"
            :close-on-press-escape="false" @close="logDialogClose" @opened="logDialogOpened">
            <el-form :model="quartzLogCondition" label-width="120px" :inline="true" class="quartz_dialog_form" 
            :rules="quartzLogRule" ref="quartzLogConditionRef">
                <el-form-item label="查询时间" prop="dateTime" style="width: 450px;">
                    <el-date-picker size="small" v-model="quartzLogCondition.dateTime" type="datetimerange"
                        start-placeholder="开始时间" end-placeholder="结束时间" format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss"/>
                </el-form-item>
                <el-form-item>
                    <el-button icon="Search" size="small" type="primary" @click="searchQuartzLog">查询</el-button>
                </el-form-item>
            </el-form>
            <el-table :data="quartzExecLogList" style="width: 100%" :show-overflow-tooltip="true" v-show="logDialogOption.type == 0">
                <el-table-column prop="jobName" label="任务名称" width="120" />
                <el-table-column prop="execStartTime" label="开始时间" width="180" />
                <el-table-column prop="execEndTime" label="结束时间" width="180"/>
                <el-table-column prop="execResult" label="执行结果"/>
            </el-table>
            <el-table :data="quartzOperateLogList" style="width: 100%" :show-overflow-tooltip="true" v-show="logDialogOption.type == 1">
                <el-table-column prop="jobName" label="任务名称" width="120" />
                <el-table-column prop="operateTime" label="操作时间" width="180" />
                <el-table-column prop="operateResult" label="操作内容"/>
            </el-table>
            <el-pagination v-model:current-page="quartzLogCondition.page" :page-size="quartzLogCondition.size"
                :pager-count="5" :small="true" :background="true" :hide-on-single-page="false"
                layout="total, sizes, prev, pager, next" :page-sizes="[10, 20, 50, 100]" :total="quartzLogCondition.total"
                @size-change="logSizeChange" @current-change="logCurrentChange" style="margin-top: 10px;"/>
        </el-dialog>
    </div>
</template>
<script>
import TableSpan from '@/components/table-span.vue';
import { tool } from "@/js/tool.js";
import { ElMessage } from 'element-plus'


export default {
    name: "quartzJob",
    data: function () {
        return {
            btOption: {
                btQuartzJobList: null,
                btQuartzJobSave: null,
                btQuartzJobUpdate: null,
                btQuartzRunOrStop: null,
                btQuartzExec: null,
                btQuartzJobDelete: null,
                btQuartzExecLog: null,
                btQuartzOperateLog: null
            },
            tabelData: {
                total: 0,
                size: 10,
                current: 1,
                records: []
            },
            quartzTypeList: [],
            quartzJobPeriodList: [],
            quartzJobStatusList: [],
            searchCondition: {
                jobName: null,
                page: 1,
                size: 10
            },
            saveUpdateDialogOption: {
                show: false,
                type: 0, //0新增；1修改
                title: ''
            },
            saveUpdateForm: {
                jobName: null,
                jobGroup: null,
                jobClassName: null,
                description: null,
                quartzType: null, //0固定频率，1cron表达式
                jobStatus: null,
                startAt: null,
                endAt: null,
                cron: null,
                interval: 1,
                repeatCount: 1
            },
            saveUpdateFormRules: {
                jobName: [
                    { required: true, message: '请填写定时任务名称', trigger: 'blur' }
                ],
                jobClassName: [
                    { required: true, message: '请填写定时任务类名称', trigger: 'blur' }
                ],
                quartzType: [
                    { required: true, message: '请选择定时任务执行频率', trigger: 'blur' }
                ],
                interval: [
                    { required: true, message: '请填写频率间隔', trigger: 'blur' }
                ],
                repeatCount: [
                    { required: true, message: '请填写重复次数', trigger: 'blur' }
                ]
            },
            logDialogOption: {
                show: false,
                type: 0, //0执行日志，1操作日志
                title: '',
                selectRow: null
            },
            quartzExecLogList: null,
            quartzOperateLogList: null,
            quartzLogCondition: {
                startDateTime: null,
                endDateTime: null,
                dateTime: [],
                jobName: null,
                total: 0,
                page: 1,
                size: 10
            },
            quartzLogRule: {
                dateTime: [
                    { required: true, message: '请选择时间范围', trigger: 'blur' }
                ]
            }
        }
    },
    methods: {
        searchData: function () {
            getShowDataList(this);
        },
        handleSizeChange: function (val) {
            this.searchCondition.page = 1;
            this.searchCondition.size = val;
            getShowDataList(this);
        },
        handleCurrentChange: function (val) {
            this.searchCondition.page = val;
            getShowDataList(this);
        },
        openDialog: function (index, row) {
            if (index == null) {
                //新增数据
                this.saveUpdateDialogOption.type = 0;
                this.saveUpdateDialogOption.title = '新增定时任务';
            } else {
                //更新数据
                this.saveUpdateDialogOption.type = 1;
                this.saveUpdateDialogOption.title = '修改定时任务';
                getJobDetail(this, row);
            }
            this.saveUpdateDialogOption.show = true;
        },
        confirmSaveUpdateDialog: function () {
            const obj = this;
            this.$refs["saveUpdateFormRef"].validate(function (valid) {
                if (valid) {
                    if (obj.saveUpdateDialogOption.type == 0) {
                        //新增
                        saveQuartzJob(obj);
                    } else {
                        //修改
                        updateQuartzJob(obj);
                    }
                }
            })
        },
        saveUpdateBeforeClose: function () {
            dialogCloseTips(this);
        },
        saveUpdateDialogClose: function () {
            this.saveUpdateForm = {
                jobName: null,
                jobGroup: null,
                jobClassName: null,
                description: null,
                quartzType: null,
                jobStatus: 0,
                startAt: null,
                endAt: null,
                cron: null,
                interval: 1,
                repeatCount: 1
            }
            this.$refs['saveUpdateFormRef'].clearValidate();
        },
        btDelete: function (index, row) {
            const obj = this;
            const confirmMessage = "是否删除当前选择的定时任务：" + row.jobName + "?";
            this.$confirm(confirmMessage).then(function () {
                const param = {
                    jobName: row.jobName,
                    jobGroup: row.jobGroup
                }
                deleteQuartzJob(obj, param);
            }).catch(function () {

            });
        },
        executeOnce: function (index, row) {
            const obj = this;
            const confirmMessage = "是否执行一次选择的定时任务：" + row.jobName + "?";
            this.$confirm(confirmMessage).then(function () {
                const param = {
                    jobName: row.jobName,
                    jobGroup: row.jobGroup
                }
                executeQuartzJob(app, param);
            }).catch(function () {

            });
        },
        jobRunOrStop: function (row) {
            const obj = this;
            row.loading = true;
            this.saveUpdateForm.jobName = row.jobName;
            this.saveUpdateForm.jobGroup = row.jobGroup;
            this.saveUpdateForm.jobStatus = row.jobStatus;
            return new Promise((resolve, reject) => {
                runOrStopQuartzJob(obj, row, resolve, reject);
            });
        },
        logDialogClose: function () {
            this.quartzExecLogList = null;
            this.quartzOperateLogList = null;

            this.logDialogOption.selectRow = null;
            this.logDialogOption.jobName = null;
            this.logDialogOption.total = 0;
            this.logDialogOption.page = 1;
            this.logDialogOption.size = 10;

            this.quartzLogCondition.dateTime = [tool.getCurDateStart(), tool.getCurDateEnd()];
        },
        openLogDialog: function (index, row, logType) {
            this.logDialogOption.show = true;
            this.logDialogOption.type = logType;
            this.logDialogOption.selectRow = row;
            this.quartzLogCondition.dateTime = [tool.getCurDateStart(), tool.getCurDateEnd()];
        },
        logDialogOpened: function(){
            getQuartzLog(this, this.logDialogOption.selectRow);
        },
        logSizeChange: function (size) {
            this.quartzLogCondition.size = size;
            this.quartzLogCondition.page = 1;
            getQuartzLog(this, this.logDialogOption.selectRow);
        },
        logCurrentChange: function (current) {
            this.quartzLogCondition.page = current;
            getQuartzLog(this, this.logDialogOption.selectRow);
        },
        searchQuartzLog: function () {
            getQuartzLog(this, this.logDialogOption.selectRow);
        }
    },
    created: function () {
        const menuId = [this.$route.query.menuId]
        const obj = this;
        new tool.getAuthorisedRequest(menuId, this.btOption, function () {
            getSysdict(obj);
            getShowDataList(obj);
        });
    },
    components: {
        TableSpan
    },
}

/**
 * 获取字典类型
 * @param app app对象
 */
function getSysdict(app) {
    app.quartzTypeList = [
        {
            value: 0,
            label: "固定频率"
        },
        {
            value: 1,
            label: "cron表达式"
        }
    ]
    const url = "/basic/dict/listByType";
    const param = ["quartz_job_period"]
    tool.formJsonRequest(url, param, null, function (data) {
        if (data.code === "0000") {
            for (let i = 0; i < data.data.length; i++) {
                let item = data.data[i];
                item.value = parseInt(item.value);
                if (item.type == "quartz_job_period") {
                    app.quartzJobPeriodList.push(item);
                }
            }
        } else {
            ElMessage({
                showClose: true,
                message: data.message,
                type: 'error'
            });
        }
    });
}

/**
 * 获取定时任务执行日志和操作日志列表
 * @param app app对象
 * @param row 行数据
 */
function getQuartzLog(app, row) {
    app.$refs["quartzLogConditionRef"].validate(function (valid) {
        if (valid) {
            if (app.logDialogOption.type == 0) {
                // 执行日志
                app.logDialogOption.title = '执行日志';
                getQuartzExecLog(app, row);
            } else {
                // 操作日志
                app.logDialogOption.title = '操作日志';
                getQuartzOperateLog(app, row);
            }
        }
    })
}

/**
 * 获取定时任务执行日志列表
 * @param app app对象
 * @param row 行数据
 */
function getQuartzExecLog(app, row) {
    let param = {
        jobName: row.jobName,
        startDateTime: app.quartzLogCondition.dateTime[0],
        endDateTime: app.quartzLogCondition.dateTime[1],
        page: app.quartzLogCondition.page,
        size: app.quartzLogCondition.size
    };
    const url = "/basic/quartz/getExecLogList";
    tool.formJsonRequest(url, param, null, function (data) {
        if (data.code === "0000") {
            app.quartzExecLogList = data.data.records;
            app.quartzLogCondition.total = data.data.total;
            app.quartzLogCondition.page = data.data.current;
            app.quartzLogCondition.size = data.data.size;
        } else {
            ElMessage({
                showClose: true,
                message: data.message,
                type: 'error'
            });
        }
    });
}

/**
 * 获取定时任务执行日志列表
 * @param app app对象
 * @param row 行数据
 */
 function getQuartzOperateLog(app, row) {
    let param = {
        jobName: row.jobName,
        startDateTime: app.quartzLogCondition.dateTime[0],
        endDateTime: app.quartzLogCondition.dateTime[1],
        page: app.quartzLogCondition.page,
        size: app.quartzLogCondition.size
    };
    const url = "/basic/quartz/getOperateLogList";
    tool.formJsonRequest(url, param, null, function (data) {
        if (data.code === "0000") {
            app.quartzOperateLogList = data.data.records;
            app.quartzLogCondition.total = data.data.total;
            app.quartzLogCondition.page = data.data.current;
            app.quartzLogCondition.size = data.data.size;
        } else {
            ElMessage({
                showClose: true,
                message: data.message,
                type: 'error'
            });
        }
    });
}

/**
 * 获取存储的定时任务列表
 * @param app app对象
 */
function getShowDataList(app) {
    let param = app.searchCondition;
    const url = "/basic/quartz/getJobList";
    tool.formJsonRequest(url, param, null, function (data) {
        if (data.code === "0000") {
            const result = data.data;
            app.tabelData = {
                total: result.total,
                size: result.size,
                current: result.current,
                records: result.records
            }
            for (let i = 0; i < result.records.length; i++) {
                let item = result.records[i];
                if (item.jobStatus == 0) {
                    item['jobStatusName'] = '启用';
                } else {
                    item['jobStatusName'] = '未启用';
                }
                if (item.execMode == 1) {
                    //bean方式
                    item['showExec'] = item.beanName;
                    item['showExecMethod'] = item.beanMethod;
                } else {
                    item['showExec'] = item.httpUrl;
                    item['showExecMethod'] = item.httpMethod;
                }
            }
        } else {
            ElMessage({
                showClose: true,
                message: data.message,
                type: 'error'
            });
        }
    });
}

/**
 * 获取定时任务详情信息
 * @param app app对象
 */
function getJobDetail(app, row) {
    const url = "/basic/quartz/getJobDetail";
    const param = {
        jobName: row.jobName,
        jobGroup: row.jobGroup
    };
    tool.formJsonRequest(url, param, null, function (data) {
        if (data.code === "0000") {
            let result = data.data;
            app.saveUpdateForm = {
                jobName: result.jobName,
                jobGroup: result.jobGroup,
                jobClassName: result.jobClassName,
                description: result.description,
                quartzType: result.quartzType, //0固定频率，1cron表达式
                jobStatus: result.jobStatus,
                startAt: result.startAt,
                endAt: result.endAt,
                cron: result.cron,
                interval: result.interval,
                repeatCount: result.repeatCount
            }
        } else {
            ElMessage({
                showClose: true,
                message: data.message,
                type: 'error'
            });
        }
    });
}

/**
 * 保存定时任务信息
 * @param app app对象
 */
function saveQuartzJob(app) {
    const url = "/basic/quartz/save";
    const param = app.saveUpdateForm;
    param.repeatCount = param.repeatCount - 1;
    tool.formJsonRequest(url, param, null, function (data) {
        if (data.code === "0000") {
            ElMessage({
                showClose: true,
                message: '保存定时任务成功',
                type: 'success'
            });
            app.searchCondition.page = 1;
            getShowDataList(app);
            app.saveUpdateDialogOption.show = false;
        } else {
            ElMessage({
                showClose: true,
                message: data.message,
                type: 'error'
            });
        }
    });
}

/**
 * 更新定时任务信息
 * @param app app对象
 */
function updateQuartzJob(app) {
    const url = "/basic/quartz/save";
    const param = app.saveUpdateForm;
    param.repeatCount = param.repeatCount - 1;
    tool.formJsonRequest(url, param, null, function (data) {
        if (data.code === "0000") {
            ElMessage({
                showClose: true,
                message: '更新定时任务成功',
                type: 'success'
            });
            getShowDataList(app);
            app.saveUpdateDialogOption.show = false;
        } else {
            ElMessage({
                showClose: true,
                message: data.message,
                type: 'error'
            });
        }
    });
}

/**
 * 停用或者启用定时任务
 * @param app app对象
 */
function runOrStopQuartzJob(app, row, resolve, reject) {
    if (app.saveUpdateForm.jobStatus == 0) {
        app.saveUpdateForm.jobStatus = 1;
    } else {
        app.saveUpdateForm.jobStatus = 0;
    }
    const url = "/basic/quartz/runOrStop";
    const param = {
        jobName: app.saveUpdateForm.jobName,
        jobGroup: app.saveUpdateForm.jobGroup
    };
    tool.formJsonRequest(url, param, function () {
        row.loading = false;
        reject(false);
    },
        function (data) {
            row.loading = false;
            if (data.code === "0000") {
                ElMessage({
                    showClose: true,
                    message: '更新定时任务状态成功',
                    type: 'success'
                });
                row.jobStatus = app.saveUpdateForm.jobStatus;
            } else {
                ElMessage({
                    showClose: true,
                    message: data.message,
                    type: 'error'
                });
            }
        });
}

/**
 * 停用或者启用定时任务
 * @param app app对象
 * @param param 请求的参数
 */
function deleteQuartzJob(app, param) {
    const url = "/basic/quartz/delete";
    tool.formJsonRequest(url, param, null, function (data) {
        if (data.code === "0000") {
            ElMessage({
                showClose: true,
                message: '删除定时任务成功',
                type: 'success'
            });
            app.searchCondition.page = 1;
            getShowDataList(app);
        } else {
            ElMessage({
                showClose: true,
                message: data.message,
                type: 'error'
            });
        }
    });
}

/**
 * 停用或者启用定时任务
 * @param app app对象
 * @param param 请求的参数
 */
function executeQuartzJob(app, param) {
    const url = "/basic/quartz/executeOnce";
    tool.formJsonRequest(url, param, null, function (data) {
        if (data.code === "0000") {
            ElMessage({
                showClose: true,
                message: '定时任务执行完成',
                type: 'success'
            });
        } else {
            ElMessage({
                showClose: true,
                message: data.message,
                type: 'error'
            });
        }
    });
}

/**
 * 弹窗关闭时的提示信息
 * @param app
 */
function dialogCloseTips(app) {
    let confirmMessage = "";
    if (app.saveUpdateDialogOption.type == 0) {
        confirmMessage = "是否放弃新增定时任务？";
    } else {
        confirmMessage = "是否放弃编辑定时任务？"
    }
    app.$confirm(confirmMessage).then(function () {
        app.saveUpdateDialogOption.show = false;
    }).catch(function () {

    });
}
</script>
<style>
.quartz_manage_span {
    position: relative;
    display: flex;
    flex-direction: row;
    width: 100%;
    height: 100%;
    font-family: Microsoft YaHei, Heiti SC, tahoma, arial, Hiragino Sans GB, "\5B8B\4F53", sans-serif;
}

.search_item_span {
    max-width: 190px;
    height: auto;
    margin-top: 5px;
    margin-left: 10px;
}

.quartz_manage_span .search_item_fix_width {
    width: 190px;
}
</style>